#include<iostream>
#include<arbb.hpp>
#include<stdio.h>
#include<cstdlib>
#include<sys/time.h>
using namespace arbb;

void Matrix_Mult(const dense<i32, 2>& A, const dense<i32,2>& B, dense<i32>& result)
{
  i32 k=0;
  dense<i32,2> Matrix_t=transpose(B);
  _for (usize i = 0, i <A.num_rows() , i++)
    {
      _for (usize j = 0, j <A.num_rows(), j++)
	{
	  result[k]=add_reduce(A.row(i) * Matrix_t.row(j));	  
	  k++;
	}_end_for;
    }_end_for;
  
}

int main ()
{
  int n=1028;
  int N=n*n;
  //  double a[N][N] , b[N][N] , c[N];
  int i;
  std::cout<<"Size is:"<<(N*sizeof(int)*3/1024)/1024<<std::endl;
  ARBB_CPP_ALIGN(int a[N]);
  ARBB_CPP_ALIGN(int b[N]);
  ARBB_CPP_ALIGN(int c[N]);
  // Setting all entires of matrix A by i*j
  for(i=0;i<N;i++)
    {
      a[i]=1.0;
      b[i]=1.0;
    }
  i=0;
  dense<i32,2> A;
  bind(A,a,n,n);
  dense<i32,2> B;
  bind(B,b,n,n);
  dense<i32> result;
  bind(result,c,N);
  // Multiplying Both matrices
  timeval tim;
  gettimeofday(&tim, NULL);
  double t1=tim.tv_sec+(tim.tv_usec/1000000.0);	
  call(Matrix_Mult)(A,B,result);
  gettimeofday(&tim, NULL);
  double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
  printf("%.6lf seconds elapsed\n", t2-t1);
  /*
  for(i=0;i<N;i++)
    {
      std::cout<<i<<". "<<c[i]<<std::endl;
    }
  std::cout<<std::endl;
  */
  return 0;
}
/*
  for( i = 0 ; i < N ; i++)
  for( j = 0 ; j < N ; j++)
  a[i][j]=i*j;
  // Setting all entires of matrix B by i+j
  for( i = 0 ; i < N ; i++)
  for( j = 0 ; j < N ; j++)
  b[i][j]=i+j;
*/

/* 
// Construct a range that can be read from and written to.
range<f32> rw_range = A.read_write_range();
rw_range[0] = 1.0f; // Set first element to 1.0f.
float second_element = rw_range[1]; // Read value of second element.

// Construct a range that can only be read.
const_range<f32> read_range = foo.read_only_range();
float third_element = read_range[2]; // Read value of third element.

// Use range iterators.
const_range<f32>::iterator begin = read_range.begin();
const_range<f32>::iterator end = read_range.end();

for (range<f32>::iterator I = begin; I != end; ++I) {
std::cout << *I << std::endl; // Print each element in the range.
}
*/
